package com.pci.netty.handler;

import cn.hutool.core.codec.BCD;
import com.pci.netty.client.BootNeetyClient;
import com.pci.netty.dto.RequestPayload;
import com.pci.netty.enums.MessageTypeEnum;
import com.pci.netty.util.RequestUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class KeepaliveHandler extends SimpleChannelInboundHandler<RequestPayload> {

    private AtomicInteger loseconnCount = new AtomicInteger(0);
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
    private BootNeetyClient client;

    public KeepaliveHandler(BootNeetyClient client) {
        this.client=client;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RequestPayload msg) throws Exception {
        byte[] head = msg.getHead();
        RequestPayload.Header header = RequestPayload.analysis(head);
        String msgCode = BCD.bcdToStr(header.getMsgCode());
        if (Objects.equals(msgCode, String.valueOf(MessageTypeEnum.HEARTBEAT.getCode()))) {
            loseconnCount.set(0);
        } else {
            ctx.fireChannelRead(msg);
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        scheduledExecutorService.scheduleAtFixedRate(()->{
            if(ctx.channel().isActive()){
                log.info("发送心跳消息...");
                RequestUtils.heartbeat(ctx);
                if(loseconnCount.incrementAndGet()>=5){
                    log.error("5个周期未收到心跳回复，客户端进行断开重连...");
                    ctx.close();
                }
            }
        },1,1, TimeUnit.SECONDS);
        super.channelActive(ctx);
    }

    /**
     * 断开连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        scheduledExecutorService.shutdownNow();
        log.error("连接断开,channelInactive:{}", ctx.channel().localAddress());
        try {
            super.channelInactive(ctx);
            client.connect();
            log.info("重连完成");
        } catch (Exception e) {
            log.error("重连失败:{}", ExceptionUtils.getStackTrace(e));
        }
    }
}
